use std::io::{Read, Write};
use serde::{Serialize, Deserialize};
use rbatis::rbdc::datetime::DateTime;

#[derive(Debug)]
#[derive(Clone)]
#[derive(lombok::Getter)]
#[derive(Serialize, Deserialize)]
pub struct ArticleSort
{
    id: u32,
    name: String
}


#[derive(Debug)]
#[derive(Clone)]
#[derive(lombok::Getter)]
#[derive(Serialize, Deserialize)]
pub struct ArticleTag
{
    id: u32,
    sort_id: u32,
    name: String
}


/*
 * 文章内容存在磁盘文件夹中
 * /article/{id}/content.md
 * /article/{id}/pic1.png
 */
#[derive(Debug)]
#[derive(Clone)]
#[derive(lombok::Getter)]
#[derive(Serialize, Deserialize)]
pub struct Article
{
    id: u32,
    author_uid: u32,
    title: Option<String>,
    upload_time: DateTime,
    update_time: DateTime,
    #[serde(skip_serializing)]
    text: Option<String>,

    sorts: Option<String>,      // 6,5,88
    tags: Option<String>        // 5,6,7,9,11,3,66
}
impl Article
{
    pub fn new(
        id: u32,
        uid: u32,
        title: &str,
        text: String,
        sorts: Option<String>,
        tags: Option<String>
    ) -> Self {
        Self {
            id,
            author_uid: uid,
            title: Some(title.to_string()),
            upload_time: DateTime::now(),
            update_time: DateTime::now(),
            text: Some(text),
            sorts,
            tags
        }
    }

    pub fn set_id(&mut self, id: u32) { self.id = id; }


    fn init_dir(&self)
    {
        let path = format!("./article/{}", self.id);
        if let Ok(_) = ::std::fs::create_dir_all(path) {
            println!("创建{}文件夹完成", format!("./article/{}", self.id));
        } else { println!("the directory maybe exists"); }
    }

    /*
     * 文章内容存在磁盘文件夹中
     * /article/{id}/content.md
     * /article/{id}/pic1.png
     */
    pub fn save_text(&self) -> ::std::io::Result<()>
    {
        if self.text.is_none() { println!("text is none");return Ok(()); }
        self.init_dir();
        let path = format!("./article/{}/content.md", self.id);
        if let Ok(_) =  ::std::fs::File::open(path.clone()) {
            ::std::fs::remove_file(path.clone())?;
        }
        let mut file = ::std::fs::File::create(path.clone())?;
        file.write_all(self.text.as_ref().unwrap().as_bytes())?;
        Ok(())
    }

    pub fn read_text(&mut self) -> ::std::io::Result<()>
    {
        let path = format!("./article/{}/content.md", self.id);
        let mut file = ::std::fs::File::open(path.clone())?;
        let mut buf = String::new();
        file.read_to_string(&mut buf)?;
        self.text = Option::Some(buf);
        Ok(())
    }
}

#[derive(Debug)]
#[derive(Clone)]
#[derive(Serialize, Deserialize)]
pub struct TestArticle
{
    pub id: u32,
    pub author_uid: u32,
    pub title: Option<String>,
    pub upload_time: DateTime,
    pub update_time: DateTime,
    pub text: Option<String>,
    pub sorts: Option<String>,      // 6,5,88
    pub tags: Option<String>        // 5,6,7,9,11,3,66
}


#[derive(Debug)]
#[derive(Clone)]
#[derive(lombok::Getter)]
#[derive(Serialize, Deserialize)]
pub struct ArticleSet
{
    id: u32,
    owner_id: u32,
    create_time: DateTime,
    name: String,
    articles_id: String
}


rbatis::crud!(ArticleSort{});
rbatis::crud!(ArticleTag{});
rbatis::crud!(Article{});
rbatis::crud!(ArticleSet{});

rbatis::impl_select!(ArticleSort {select_by_id(id: &str) -> Option => "`where id = #{id} limit 1`"});
rbatis::impl_update!(ArticleSort {update_by_id(id: &str) => "`where id = #{id}`"});
rbatis::impl_delete!(ArticleSort {delete_by_id(id: &str) => "`where id = #{id}`"});

rbatis::impl_select!(ArticleTag {select_by_id(id: &str) -> Option => "`where id = #{id} limit 1`"});
rbatis::impl_update!(ArticleTag {update_by_id(id: &str) => "`where id = #{id}`"});
rbatis::impl_delete!(ArticleTag {delete_by_id(id: &str) => "`where id = #{id}`"});

rbatis::impl_select!(Article {select_by_id(id: &str) -> Option => "`where id = #{id} limit 1`"});
rbatis::impl_delete!(Article {delete_by_id(id: &str) => "`where id = #{id}`"});

rbatis::impl_select!(ArticleSet {select_by_id(id: &str) -> Option => "`where id = #{id} limit 1`"});
rbatis::impl_update!(ArticleSet {update_by_id(id: &str) => "`where id = #{id}`"});
rbatis::impl_delete!(ArticleSet {delete_by_id(id: &str) => "`where id = #{id}`"});


